package com.battery.system.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.battery.common.core.domain.AjaxResult;
import com.battery.common.enums.OrderTradeStateEnum;
import com.battery.common.enums.RefundStatusEnum;
import com.battery.common.enums.UsedStatusEnum;
import com.battery.common.utils.BatteryJSONResult;
import com.battery.common.utils.Constants;
import com.battery.common.utils.DateUtils;
import com.battery.common.utils.GenerateSeqUtil;
import com.battery.common.utils.ali.AliPayEntity;
import com.battery.common.utils.ali.AliPayUtils;
import com.battery.system.domain.*;
import com.battery.system.domain.BO.RefundApplyBO;
import com.battery.system.domain.VO.RefundApplyVO;
import com.battery.system.mapper.*;
import com.battery.system.service.battery.IIncomeService;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import org.apache.commons.lang3.StringUtils;
import org.n3r.idworker.Sid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.battery.system.service.IRefundApplyService;
import com.battery.common.core.text.Convert;
import tk.mybatis.mapper.entity.Example;

/**
 * 订单退款申请Service业务层处理
 *
 * @author battery
 * @date 2021-03-12
 */
@Service
public class RefundApplyServiceImpl extends BaseServiceImpl<RefundApply> implements IRefundApplyService {


    //  微信支付
    @Autowired(required = false)
    private WxPayService wxService;

    @Autowired
    private RefundApplyMapper refundApplyMapper;


    @Autowired
    private UsedMapper usedMapper;


    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private RefundOrderMapper refundOrderMapper;

    @Autowired
    private AppUserMapper appUserMapper;


    @Autowired
    private IIncomeService incomeService;


    @Autowired
    private Sid sid;


    /**
     * 查询订单退款申请
     *
     * @param id 订单退款申请ID
     * @return 订单退款申请
     */
    @Override
    public RefundApply selectRefundApplyById(String id) {
        return refundApplyMapper.selectRefundApplyById(id);
    }

    /**
     * 查询订单退款申请列表
     *
     * @param refundApply 订单退款申请
     * @return 订单退款申请
     */
    @Override
    public List<RefundApply> selectRefundApplyList(RefundApply refundApply) {
        return refundApplyMapper.selectRefundApplyList(refundApply);
    }

    /**
     * 新增订单退款申请
     *
     * @param refundApply 订单退款申请
     * @return 结果
     */
    @Override
    public int insertRefundApply(RefundApply refundApply) {
        return refundApplyMapper.insertRefundApply(refundApply);
    }

    /**
     * 修改订单退款申请
     *
     * @param refundApply 订单退款申请
     * @return 结果
     */
    @Override
    public int updateRefundApply(RefundApply refundApply) {
        return refundApplyMapper.updateRefundApply(refundApply);
    }

    /**
     * 删除订单退款申请对象
     *
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteRefundApplyByIds(String ids) {
        return refundApplyMapper.deleteRefundApplyByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除订单退款申请信息
     *
     * @param id 订单退款申请ID
     * @return 结果
     */
    @Override
    public int deleteRefundApplyById(String id) {
        return refundApplyMapper.deleteRefundApplyById(id);
    }

    @Override
    public List<RefundApply> selectRefundApplyByPartner(Map<String, String> map) {
        return refundApplyMapper.selectRefundApplyByPartner(map);
    }

    /**
     * 退款申请列表
     *
     * @param refundApplyBO
     * @return
     */
    @Override
    public List<RefundApplyVO> selectRefundApplyVOList(RefundApplyBO refundApplyBO) {
        return refundApplyMapper.selectRefundApplyVOList(refundApplyBO);
    }

    /**
     * 通过并进行退款操作
     *
     * @param refundApplyId
     * @param aliPayEntity
     * @return
     */
    @Override
    public AjaxResult adoptRefund(String refundApplyId, AliPayEntity aliPayEntity) {

        RefundApply refundApply = refundApplyMapper.selectByPrimaryKey(refundApplyId);

        BigDecimal refund_fee = refundApply.getPrice(); // 需退款金额
        String refundDesc = refundApply.getReason();
        // 查询对应的租借订单
        Used used = usedMapper.selectByPrimaryKey(refundApply.getUsedId());
        // 通过租借记录查找对应的支付订单
        Order order = orderMapper.selectByPrimaryKey(used.getTrueOrderId()); // 真正的支付订单
        if (order == null) {
            return AjaxResult.error("未查找到对应的支付订单，请联系管理员");
        }

        Example example = new Example(RefundOrder.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("orderId", order.getId());
        criteria.andEqualTo("refundStatus", RefundStatusEnum.CHANGE.getCode()); // 退款异常
        RefundOrder errRefund = refundOrderMapper.selectOneByExample(example);

        AppUser appUser = appUserMapper.selectByPrimaryKey(order.getAppUserId());

        String out_refund_no = ""; // 退款单号
        String refundOrderId = null;
        if (errRefund != null) {
            out_refund_no = errRefund.getOutRefundNo();
            RefundOrder orderUpdate = new RefundOrder();
            orderUpdate.setId(errRefund.getId());
            orderUpdate.setRefundFee(refund_fee);
            orderUpdate.setRefundStatus(RefundStatusEnum.REQUEST_REFUND.getCode()); // 发起退款

            refundOrderMapper.updateByPrimaryKeySelective(orderUpdate);

            refundOrderId = errRefund.getId();
        } else {
            out_refund_no = GenerateSeqUtil.generateEndRadomCode() + GenerateSeqUtil.getRandomCode(6);

            RefundOrder refundOrder = new RefundOrder();
            refundOrder.setId(sid.nextShort());
            refundOrder.setAppUserId(appUser.getId());
            refundOrder.setOutRefundNo(out_refund_no);
            refundOrder.setTotalFee(order.getTotalFee());
            refundOrder.setRefundFee(refund_fee);
            refundOrder.setRefundDesc(refundDesc); // 退款描述
            refundOrder.setRefundStatus(RefundStatusEnum.REQUEST_REFUND.getCode()); // 发起退款
            refundOrder.setCreateTime(DateUtils.getNowDate());
            refundOrder.setOrderId(order.getId());
            refundOrder.setOrderType(order.getOrderType());
            refundOrder.setChannel(order.getChannel());
            refundOrderMapper.insertSelective(refundOrder);
            // 查询新建的退款数据
            refundOrderId = refundOrder.getId();
        }

        // 订单渠道 微信 1 支付宝 2
        if (order.getChannel().intValue() == 1) {
            WxPayRefundRequest refundRequest = new WxPayRefundRequest();
            refundRequest.setTransactionId(order.getTransactionId());
            refundRequest.setOutRefundNo(out_refund_no);
            refundRequest.setTotalFee(order.getTotalFee().multiply(new BigDecimal(100)).intValue());
            refundRequest.setRefundFee(refund_fee.multiply(new BigDecimal(100)).intValue());
            refundRequest.setNotifyUrl(Constants.wx_refund_callback_url); // 退款通知接口
            WxPayRefundResult refundResult = null;
            boolean flag = false;
            try {
                refundResult = wxService.refund(refundRequest);
            } catch (WxPayException e) {
                // 发生错误
                e.printStackTrace();
                flag = true;
            }
            if (refundResult == null || flag) {

                RefundApply refundApplyUpdate = new RefundApply();
                refundApplyUpdate.setId(refundApply.getId());
                // 退款状态 1、待审批   2、退款成功  3、退款失败
                refundApplyUpdate.setRefundStatus(3); // 退款失败
                // 审核状态 1、审核中，2、已通过，3、已拒绝
                refundApplyUpdate.setAuditStatus(2);
                refundApplyUpdate.setAuditTime(DateUtils.getNowDate());
                refundApplyMapper.updateByPrimaryKeySelective(refundApplyUpdate);

                // 调起微信退款接口发生错误
                RefundOrder updateRefundOrder = new RefundOrder();
                updateRefundOrder.setRefundStatus(RefundStatusEnum.CHANGE.getCode()); // 退款异常
                updateRefundOrder.setId(refundOrderId);
                updateRefundOrder.setRemark("发起退款出现异常");
                refundOrderMapper.updateByPrimaryKeySelective(updateRefundOrder);
                return AjaxResult.error("发起退款出现异常");
            }
            String return_code = refundResult.getReturnCode();
            String result_code = refundResult.getResultCode();
            if ("SUCCESS".equals(return_code) && "SUCCESS".equals(result_code)) {

                RefundApply refundApplyUpdate = new RefundApply();
                refundApplyUpdate.setId(refundApply.getId());
                // 审核状态 1、审核中，2、已通过，3、已拒绝
                refundApplyUpdate.setAuditStatus(2);
                refundApplyUpdate.setAuditTime(DateUtils.getNowDate());
                refundApplyMapper.updateByPrimaryKeySelective(refundApplyUpdate);


                String refund_id = refundResult.getRefundId(); // 微信退款单号
                RefundOrder updateRefundOrder = new RefundOrder();
                updateRefundOrder.setId(refundOrderId);
                updateRefundOrder.setRefundId(refund_id);
                updateRefundOrder.setRefundStatus(RefundStatusEnum.REQUEST_REFUND.getCode()); // 发起退款
                refundOrderMapper.updateRefundOrder(updateRefundOrder);

                // 更新原先订单状态
                Order updateFormer = new Order();
                updateFormer.setId(order.getId());
                updateFormer.setTradeState(OrderTradeStateEnum.TO_REFUND.getCode()); // 转入退款
                updateFormer.setRefundId(out_refund_no); // 退款订单号
                updateFormer.setRefundMoney(refund_fee); // 退款金额
                updateFormer.setRefundDesc(refundDesc); // 退款描述
                orderMapper.updateByPrimaryKeySelective(updateFormer);

                // TODO TODO 注意：微信进行退款操作，更新租借记录信息 在回调里面进行操作

                return AjaxResult.success("退款成功，退款金额为" + refund_fee + "元");
            }

            RefundApply refundApplyUpdate = new RefundApply();
            refundApplyUpdate.setId(refundApply.getId());
            // 退款状态 1、待审批   2、退款成功  3、退款失败
            refundApplyUpdate.setRefundStatus(3); // 退款失败
            // 审核状态 1、审核中，2、已通过，3、已拒绝
            refundApplyUpdate.setAuditStatus(2);
            refundApplyUpdate.setAuditTime(DateUtils.getNowDate());
            refundApplyMapper.updateByPrimaryKeySelective(refundApplyUpdate);


            // 调起微信退款接口发生错误
            RefundOrder updateRefundOrder = new RefundOrder();
            updateRefundOrder.setRefundStatus(RefundStatusEnum.CHANGE.getCode()); // 退款异常
            updateRefundOrder.setId(refundOrderId);
            updateRefundOrder.setRemark("发起退款出现异常");
            refundOrderMapper.updateByPrimaryKeySelective(updateRefundOrder);
            return AjaxResult.error("退款失败,微信返回【" + refundResult.getErrCodeDes() + "】"); // 返回错误描述
        } else {
            // 支付宝退款
            JSONObject requestRefundObj = new JSONObject();
            requestRefundObj.put("out_trade_no", order.getOutOrderNo());
            requestRefundObj.put("trade_no", order.getTransactionId());
            requestRefundObj.put("out_request_no", out_refund_no);
            requestRefundObj.put("refund_amount", refund_fee);
            BatteryJSONResult result = null;
            boolean flag = false;
            try {
                result = AliPayUtils.tradeRefund(aliPayEntity, requestRefundObj);
            } catch (Exception e) {
                e.printStackTrace();
                flag = true;
            }
            if (result == null || flag || result.getCode().intValue() != 1) {


                RefundApply refundApplyUpdate = new RefundApply();
                refundApplyUpdate.setId(refundApply.getId());
                // 退款状态 1、待审批   2、退款成功  3、退款失败
                refundApplyUpdate.setRefundStatus(3);
                // 审核状态 1、审核中，2、已通过，3、已拒绝
                refundApplyUpdate.setAuditStatus(2);
                refundApplyUpdate.setAuditTime(DateUtils.getNowDate());
                refundApplyMapper.updateByPrimaryKeySelective(refundApplyUpdate);


                // 支付宝退款抛出异常
                RefundOrder updateRefundOrder = new RefundOrder();
                updateRefundOrder.setRefundStatus(RefundStatusEnum.CHANGE.getCode()); // 退款异常
                updateRefundOrder.setId(refundOrderId);
                updateRefundOrder.setRemark("发起退款出现异常");
                refundOrderMapper.updateByPrimaryKeySelective(updateRefundOrder);
                return AjaxResult.error("发起退款出现异常");
            }
            AlipayTradeRefundResponse response = (AlipayTradeRefundResponse) result.getData();
            if (response.isSuccess()) {
                Date paySuccessTime = DateUtils.getNowDate();


                RefundApply refundApplyUpdate = new RefundApply();
                refundApplyUpdate.setId(refundApply.getId());
                // 退款状态 1、待审批   2、退款成功  3、退款失败
                refundApplyUpdate.setRefundStatus(2);
                // 审核状态 1、审核中，2、已通过，3、已拒绝
                refundApplyUpdate.setAuditStatus(2);
                refundApplyUpdate.setAuditTime(paySuccessTime);
                refundApplyMapper.updateByPrimaryKeySelective(refundApplyUpdate);

                // 退款成功
                RefundOrder updateRefundOrder = new RefundOrder();
                updateRefundOrder.setId(refundOrderId);
                updateRefundOrder.setRefundStatus(RefundStatusEnum.SUCCESS.getCode());
                updateRefundOrder.setSuccessTime(paySuccessTime);
                refundOrderMapper.updateByPrimaryKeySelective(updateRefundOrder);

                // 支付宝直接设定为退款成功
                // 更新原先订单状态
                Order updateFormer = new Order();
                updateFormer.setId(order.getId());
                updateFormer.setTradeState(OrderTradeStateEnum.REFUND_SUCCESS.getCode()); // 转入退款
                updateFormer.setRefundId(out_refund_no); // 退款订单号
                updateFormer.setRefundMoney(refund_fee); // 退款金额
                orderMapper.updateByPrimaryKeySelective(updateFormer);

                // TODO TODO 退款成功之后，更新对应租借订单状态
                if (StringUtils.isNotBlank(order.getUsedId())) {
                    Used usedUpdate = new Used();
                    usedUpdate.setId(order.getUsedId());
                    usedUpdate.setRefundAmount(refund_fee);
                    usedUpdate.setStatus(UsedStatusEnum.REFUND_SUCCESS.getCode());
                    usedMapper.updateByPrimaryKeySelective(usedUpdate);
                }
                // TODO TODO 退款成功之后，进行退分润操作

                try {
                    // 进行退分润操作
                    incomeService.refundShareMoney(order.getUsedId(), order.getId(), refundOrderId);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return AjaxResult.success("退款成功，退款金额为" + refund_fee + "元");
            }

            RefundApply refundApplyUpdate = new RefundApply();
            refundApplyUpdate.setId(refundApply.getId());
            refundApplyUpdate.setRefundStatus(3); // 退款失败
            // 审核状态 1、审核中，2、已通过，3、已拒绝
            refundApplyUpdate.setAuditStatus(2);
            refundApplyUpdate.setAuditTime(DateUtils.getNowDate());
            refundApplyMapper.updateByPrimaryKeySelective(refundApplyUpdate);

            RefundOrder updateRefundOrder = new RefundOrder();
            updateRefundOrder.setRefundStatus(RefundStatusEnum.CHANGE.getCode()); // 退款异常
            updateRefundOrder.setId(refundOrderId);
            updateRefundOrder.setRemark("发起退款出现异常");
            refundOrderMapper.updateByPrimaryKeySelective(updateRefundOrder);
            return AjaxResult.error("退款失败,支付宝返回【" + response.getSubMsg() + "】"); // 返回错误描述
        }
    }

    /**
     * @param usedId
     * @return
     */
    @Override
    public boolean selectCountByUsedId(String usedId) {
        Example example = new Example(RefundApply.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("usedId", usedId);
        return refundApplyMapper.selectCountByExample(example) > 0;
    }


    @Override
    public RefundApply selectOneByUsedId(String usedId) {
        Example example = new Example(RefundApply.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("usedId", usedId);
        return refundApplyMapper.selectOneByExample(example);
    }
}
